#!/usr/bin/env python
# encoding: utf-8
"""
mp3wav.py

Created by Isaac Wang on 2010-03-01 for MUS 422 Final Project
"""
import os
import numpy as np
import scipy.io.wavfile as wav

savedOffset = 0

def wavToMp3(inputFile, bitRate):
    """
    Converts a wav file to an mp3 using LAME
    
    args: inputFile - string of the path of the .wav file (must end in .wav)
          bitRate - bitRate of encoded mp3
    """
    outputFile = inputFile[:-4] + str(bitRate) + '.row.mp3'
    os.system('lame -b %s -h %s %s' % (bitRate, inputFile, outputFile))
    return outputFile


def mp3ToWav(inputFile, sampleRate = 44100):
    """
    Converts an mp3 to wav file using mpg123
    
    args: inputFile - string of the path of the .mp3 file (must end in .mp3)
    """
    outputFile = inputFile[:-4] + '.wav'
    os.system('mpg123 -q -r %d -w %s %s' % (sampleRate, outputFile, inputFile))
    return outputFile

def findDifference(inputFile, bitRate):
    """
    Finds the difference between the input wav file and that file coded as an mp3
    
    args: inputFile - string of the path of the .wav file (must end in .wav)
          bitRate - bit rate of mp3 to compare the wav file to (common rates include 128, 192, 256, and 320)
    """
    mp3File = wavToMp3(inputFile, bitRate)
    recodedWavFile = mp3ToWav(mp3File)
    
    w = wav.read(inputFile)
    w2 = wav.read(recodedWavFile)

    # First big value to look for
    bigVal = 5000
    
    # Where a the first big value appears in w
    wFirstBig = 0;
    while (True):
      # If the current vale is big enough, break
      if ( np.abs(w[1][wFirstBig][0]) > bigVal ):
        break;
      # Otherwise, check next index
      wFirstBig = wFirstBig + 1
      
    # Same for w2
    w2FirstBig = 0;
    while (True):
      if ( np.abs(w2[1][w2FirstBig][0]) > bigVal ):
        break;
      w2FirstBig = w2FirstBig + 1
    
    # Get the smaller of the sizes of the arrays after the first big value
    wCroppedSize = np.size( w[1][wFirstBig:-1][:,0] )
    w2CroppedSize = np.size( w2[1][w2FirstBig:-1][:,0] )
    wSmaller = min( wCroppedSize, w2CroppedSize  )
    
    # Subtract them
    diffW = abs(w[1][wFirstBig : wFirstBig + wSmaller] - w2[1][w2FirstBig : w2FirstBig + wSmaller])
    
    diffFile = inputFile[:-4] + '.diff.wav'
    wav.write(diffFile,w[0],diffW)
    
    return (diffFile, mp3File)

def synthesizeWav(mp3File, errorWav):
    """
    Synthesizes wav from with error
    """
    mp3AsWav = mp3ToWav(mp3File)
    
    w = wav.read(mp3AsWav)
    # ww1 = np.cast['int32'](w[1])
    # for i in xrange(len(w[1])):
    #     w[1][i] = np.cast['int32'](w[1][i])
    # print w
    # wav.write(mp3File[:-4] + '.recoded.wav',w[0],w[1])
    w2 = wav.read(errorWav)
    # ww2 = np.cast['int32'](w2[1])
    # for i in xrange(len(w2[1])):
    #     w2[1][i] = np.cast['int32'](w2[1][i])    
    #diff = abs(len(w[1]) - len(w2[1]))
    
    # First big value to look for
    bigVal = 100
    
    # Where a the first big value appears in w
    wFirstBig = 0;
    while (wFirstBig < len(w[1])):
      # If the current vale is big enough, break
      if ( np.abs(w[1][wFirstBig][0]) > bigVal ):
        break;
      # Otherwise, check next index
      wFirstBig = wFirstBig + 1
      
    # Same for w2
    w2FirstBig = 0;
    while (w2FirstBig < len(w2[1])):
      if ( np.abs(w2[1][w2FirstBig][0]) > bigVal ):
        break;
      w2FirstBig = w2FirstBig + 1
    
    # Get the smaller of the sizes of the arrays after the first big value
    wCroppedSize = np.size( w[1][wFirstBig:-1][:,0] )
    w2CroppedSize = np.size( w2[1][w2FirstBig:-1][:,0] )
    wSmaller = min( wCroppedSize, w2CroppedSize  )
    
    # Sum them
    combinedW = w[1][wFirstBig : wFirstBig + wSmaller] + w2[1][w2FirstBig : w2FirstBig + wSmaller]
    # import pylab
    #     pylab.plot(combinedW)
    # combinedW = ww1[wFirstBig : wFirstBig + wSmaller] + ww2[w2FirstBig : w2FirstBig + wSmaller]
    # combinedW = np.clip(-32766,32766,combinedW)
    # combinedW = np.cast['int16'](combinedW)
    # print combinedW
    # for i in xrange(len(combinedW) - 1):
    #     for j in xrange(len(combinedW[0])):
    #         if abs(combinedW[i][j]  - combinedW[i+1][j]) > 40000:
    #             print 'hey!!!'
    # print combinedW
    # combinedW = combinedW * 0.97
    # print combinedW
    # for i in xrange(len(combinedW)):
    #     for j in xrange(len(combinedW[0])):
    #         combinedW[i][j] = np.cast['int32'](combinedW[i][j])
    # print combinedW
    
    wav.write(mp3File[:-4] + '.final.wav',w[0],combinedW)

if __name__ == "__main__":    
    # inputFile = raw_input("Filename to convert (must end in .wav): ")
    # bitRate = raw_input("Bitrate: ")
    # findDifference(inputFile, bitRate)
    
    # mp3File = raw_input("mp3File: ")
    # errorWav = raw_input("errorWav: ")
    # mp3File = 'drums128.row.mp3'
    # errorWav = 'drums128.row.error.wav'
    # synthesizeWav(mp3File, errorWav)
    
    inFile = raw_input('in: ')
    bitRate = raw_input('br: ')
    bitRate = int(bitRate)
    
    wavAsMp3 = wavToMp3(inFile, bitRate)
    mp3AsWav = mp3ToWav(wavAsMp3)
    
    w = wav.read(inFile)
    w2 = wav.read(mp3AsWav)
    wav.write(inFile[:-4] + "small.wav", w2[0],w2[1])
    
    # First big value to look for
    bigVal = 10000
    
    # Where a the first big value appears in w
    wFirstBig = 0;
    while (True):
      # If the current vale is big enough, break
      if ( np.abs(w[1][wFirstBig][0]) > bigVal ):
        break;
      # Otherwise, check next index
      wFirstBig = wFirstBig + 1
      
    # Same for w2
    w2FirstBig = 0;
    while (True):
      if ( np.abs(w2[1][w2FirstBig][0]) > bigVal ):
        break;
      w2FirstBig = w2FirstBig + 1
    
    # Get the smaller of the sizes of the arrays after the first big value
    wCroppedSize = np.size( w[1][wFirstBig:-1][:,0] )
    w2CroppedSize = np.size( w2[1][w2FirstBig:-1][:,0] )
    wSmaller = min( wCroppedSize, w2CroppedSize  )
    
    # PLOTTING
    import pylab
    pylab.subplot(411)
    pylab.plot( w[1][wFirstBig : wFirstBig + wSmaller])
    
    pylab.subplot(412)
    pylab.plot( w2[1][w2FirstBig : w2FirstBig + wSmaller])
    
    pylab.subplot(413)
    pylab.plot( w[1])
    
    pylab.subplot(414)
    pylab.plot( w2[1])
    pylab.show()
    
    # Subtract them
    diffW = abs(w[1][wFirstBig : wFirstBig + wSmaller] - w2[1][w2FirstBig : w2FirstBig + wSmaller])
    pylab.figure(2)
    pylab.plot(diffW)
    pylab.show()
    
    wav.write(inFile[:-4] + '.diff.wav',w[0],diffW)